package com.wqz.tacos.controller;

import com.wqz.tacos.data.IngredientRepository;
import com.wqz.tacos.data.TacoRepository;
import com.wqz.tacos.impl.JdbcIngredientRepository;
import com.wqz.tacos.models.Ingredient;
import com.wqz.tacos.models.Order;
import com.wqz.tacos.models.Taco;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

// 处理http请求或者将http请求传递给视图，又或者将数据直接写入响应体Restful
// Slf4j用于生成logger
// Controller将会标注这个类为控制器类
// RequestMapping用于类级别的时候可以显示地规定该类只会处理路径以"/design"开头的请求
@Slf4j
@Controller
@RequestMapping("/design")
@SessionAttributes("order")
public class DesignTackController {

    // 注入和使用repository
    private final IngredientRepository ingredientRepository;
    private final TacoRepository tacoRepository;

    // 通过Autowired注入
    @Autowired
    public DesignTackController(IngredientRepository ingredientRepository, TacoRepository tacoRepository) {
        this.ingredientRepository = ingredientRepository;
        this.tacoRepository = tacoRepository;
    }

    //@GetMapping
//    @ModelAttribute()
//    public void addIngredientToModel(Model model) {
        // 直接构造数据
//        List<Ingredient> ingredients = Arrays.asList(
//                new Ingredient("FLTO", "Flour Tortilla", Ingredient.Type.WRAP),
//                new Ingredient("COTO", "Corn Tortilla", Ingredient.Type.WRAP),
//                new Ingredient("GRBF", "Ground Beef", Ingredient.Type.PROTEIN),
//                new Ingredient("CARN","Carnitas", Ingredient.Type.PROTEIN),
//                new Ingredient("TMTO", "Carnitas", Ingredient.Type.VEGGIES),
//                new Ingredient("LETC", "Lettuce", Ingredient.Type.VEGGIES),
//                new Ingredient("CHED", "Cheddar", Ingredient.Type.CHEESES),
//                new Ingredient("JACK", "Monterrey Jack", Ingredient.Type.CHEESES),
//                new Ingredient("SLSA", "Salsa", Ingredient.Type.SAUCES),
//                new Ingredient("SRCR", "Sour Cream", Ingredient.Type.SAUCES)
//        );

//        List<Ingredient> ingredients = new ArrayList<>();
//        ingredientRepository.findAll().forEach(i -> ingredients.add(i));
//        log.info("after use repository, ingredients is %s", ingredients.toString());
//
//        // 根据配料类型过滤列表
//        Ingredient.Type[] types = Ingredient.Type.values();
//        for (Ingredient.Type type : types) {
//            model.addAttribute(type.toString().toLowerCase(), filterByType(ingredients, type));
//        }
//    }

    /**
     * 使用ModelAttribute注解代替每次手动创建对象
     * 会在每个处理请求的方法之前先调用一次
     * @return
     */
    @ModelAttribute(name = "taco")
    public Taco taco() {
        return new Taco();
    }

    @ModelAttribute(name="order")
    public Order order() {
        return new Order();
    }

    // showDesignForm[]
    // 这里按照书上的会出错，mapping有问题

    /**
     * 处理获取design页面的get请求
     * @param model
     * @return
     */
    @GetMapping
    public String showDesignForm(Model model) {

        List<Ingredient> ingredients = new ArrayList<>();
        ingredientRepository.findAll().forEach(i -> ingredients.add(i));
        // log.info("after use repository, ingredients is %s", ingredients.toString());

        // 根据配料类型过滤列表
        Ingredient.Type[] types = Ingredient.Type.values();
        for (Ingredient.Type type : types) {
            model.addAttribute(type.toString().toLowerCase(), filterByType(ingredients, type));
        }
        // model.addAttribute("design", new Taco());
        return "design";
    }

    /**
     * Order对象为参数，且@ModelAttribute注解能够确保会在model中创建一个Order对象
     * 处理design页面的点击button的post请求
     * @param design
     * @param errors
     * @param order
     * @return
     */
    @PostMapping
    public String processDesign(@Valid Taco design, Errors errors, @ModelAttribute Order order) {
        if (errors.hasErrors()) {
            log.info("ingredient error occurred and it is " + errors.toString());
            return "design";
        }
        // Save the taco design...
        log.info("Processing design: " + design);
        Taco saved = tacoRepository.save(design);
        order.addDesign(saved);

        return "redirect:/orders/current";
    }

    private List<Ingredient> filterByType(List<Ingredient> ingredients, Ingredient.Type type) {
        return ingredients
                .stream()
                .filter(x -> x.getType().equals(type))
                .collect(Collectors.toList());
    }
}
